import cn from 'classnames';
import PropTypes from 'prop-types';
import React, { useEffect, useMemo, useState } from 'react';
import fetch from 'API/fetch';
import Empty from '../../../../../../components/empty/EmptyData';
import Table from '@knownsec/react-component/dist/Table'
import { millisecond } from '../../../../../../../common/formatter';
import Dialog from '@knownsec/react-component/dist/Dialog';
import Tooltip from '@knownsec/react-component/dist/Tooltip';
import Icon from '@knownsec/react-component/dist/Icon';
import Form from '@knownsec/react-component/dist/Form';
import Datetime from '@knownsec/react-component/dist/Datetime'
import Pagination from '@knownsec/react-component/dist/Pagination'
import Select from '@knownsec/react-component/dist/Select'
import Loading from '@knownsec/react-component/dist/Loading'
import TaskResult from '../../../../../../components/AviliableTaskResult';
import resultNumbers from '../resultNumbers';
import s from './style.module.css';
import dayjs from 'dayjs';
import moment from 'moment';
import ms from 'ms';
import { cloneDeep } from 'lodash'
import { NODE_ID_LABEL_MAP2, FREQUENCY_UNIT_MAP as UNIT } from '../../../../../../../common/constants';
const defaultFilter = {
	page: 1,
	limit: 10,
};
function InfoTable({ className, jobId, target, taskType, data, type='last' }) {
	const aviliableNode = JSON.parse(sessionStorage.aviliableNode) || null;
	const minDate = JSON.parse(sessionStorage.getItem('resD'))?.balance?.aviliableMaxHistory?.total || 60
	const [visible, setVisible] = useState(false)
	const [historyData, setHistoryData] = useState([])
	const [dateRange, setDateRange] = useState([moment().startOf('day'), moment()])
	const [loading, setLoading] = useState(false)
	const [taskSettings, setTaskSettings] = useState(null)
	const [filter, setFilter] = useState(defaultFilter)
	const [total, setTotal] = useState(0)

	const disableDate = (current) => {
		const maxToday = current.diff(moment(), 'days', true) >= 0
		const min60Day = current.diff(moment().subtract(minDate > 60 ? 60 : minDate, 'days'), 'days', true) <= 0
		return maxToday || min60Day
	}
	const columns = type === 'last' ? [
		{
			title: '监测节点',
			dataIndex: 'area',
			key: 'area',
			render (e) {
				return <div title={e}>{e}</div>
			}
		},
		{
			title: '监测类型',
			dataIndex: 'networkDisplayName',
			key: 'networkDisplayName',
			render (e) {
				return <div title={e}>{e}</div>
			}
		},
		{
			title: '响应服务器IP',
			dataIndex: 'ip',
			key: 'ip',
			render (e) {
				return <div title={e || '- -'}>{e || '- -'}</div>
			}
		},
		...(taskType === 'http' ? [{
			title: '响应状态码',
			dataIndex: 'statusCode',
			key: 'statusCode',
			render (e) {
				return e ? <div title={e}>{e}</div> : '- -'
			}
		}] : []),
		{
			title: '总响应时间',
			dataIndex: 'totalTime',
			key: 'totalTime',
			render (e) {
				return e ? millisecond(e) : '- -'
			}
		},
		{
			title: '监测结果',
			dataIndex: 'securityStatus',
			key: 'securityStatus',
			render (e) {
				return <span className={cn({
					[s.errorColor]: ['warning', 'error'].includes(e),
					[s.successColor]: e === 'safe',
				})}>{e === 'warning' ? '异常' : e === 'error' ? '节点出错' : '正常'}</span>
			}
		},
		{
			title: '操作',
			dataIndex: 'method',
			key: 'method',
			render (e, row) {
				return row.securityStatus !== 'error' ? <TaskResult
					securityStatus={row.securityStatus}
					result={row}
					type="text"
					taskType={row.taskType}
					withoutIcon={true}
				/> : '- -'
			}
		},
	] : [
		{
			title: '任务名称',
			dataIndex: 'name',
			key: 'name'
		},
		{
			title: '响应正常节点',
			dataIndex: 'node',
			key: 'node',
			render (e, row) {
				const settingsNodeTotal = (row?.taskSettings?.collect?.area?.length || 0) + (row?.taskSettings?.collect?.area_ipv6?.length || 0)
				return `${(row?.result?.addition?.nodeTotalCount - row?.result?.addition?.nodeAbnormalCount) < 0 ? 0 : (row?.result?.addition?.nodeTotalCount - row?.result?.addition?.nodeAbnormalCount)}/${settingsNodeTotal}`
			}
		},
		{
			title: '平均响应时间',
			dataIndex: 'respAvg',
			key: 'respAvg',
			render (e, row) {
				return millisecond(row?.result?.addition?.respAvg)
			}
		},
		{
			title: '监测结果',
			dataIndex: 'securityStatus',
			key: 'securityStatus',
			render (e) {
				return <span className={cn({
					[s.errorColor]: e === 'warning',
					[s.successColor]: e === 'safe',
				})}>{e === 'warning' ? '异常' : '正常'}</span>
			}
		},
		{
			title: '监测完成时间',
			dataIndex: 'endTime',
			key: 'endTime',
			render (e) {
				return moment(e).format('YYYY-MM-DD HH:mm:ss')
			}
		},
	]
	const timeChange = value => {
		let unit;
		let num;
		if (value) {
			const freq = ms(value);
			unit = value ? freq.replace(/\d*/, '') : 'd';
			num = parseInt(freq.replace(/[a-zA-Z]/, ''), 10);
			if (value % ms('30d') === 0) {
				unit = 'month';
				num = value / ms('30d');
			} else if (value % ms('1w') === 0) {
				unit = 'w';
				num = value / ms('1w');
			}
		}
		return `${num}${UNIT[unit] || '毫秒'}`;
	};

	const getData = async date => {
		let [st, et] = dateRange
		st = st.startOf('day').toISOString()
		et = et.endOf('day').toISOString()
		setLoading(true);
		const target_=encodeURIComponent(target)
		const url = `/api/v2/repodatas/report-task?jobId=${jobId}&taskType=${taskType}&range=range&target=${target_}&startTime=${st}&endTime=${et}`;
		const res = await fetch(url, {
			method: 'GET',
		}).catch(() => setHistoryData([]));
		const resultList = res?.TaskData?.map(item => {
			item.key = item._id
			return item
		})
		setHistoryData(resultList || [])
		setLoading(false);
	}

	const handleDateChange = (dateRange, string) => {
		if (loading) return fasle
		if (dateRange.length === 2) {
			if (dateRange[1].diff(dateRange[0].add(7, 'days')) >= 0) {
				dateRange[1] = dateRange[0].add(7, 'days').endOf('day')
			}
		}
		setDateRange(dateRange)
	};
	const handleChangeSearch = e => {
		e && setFilter({ ...filter, ...e });
	};
	const taskContent = (data, map, text) => {
		let res = '- -'
		if (data?.length > 0) {
			if (data.length > 1) {
				res = <>
					{data.slice(0, 1).map(item => { return map[item] }).join('、')}等{data.length}个监测节点
					<Tooltip overlay={<div style={{maxWidth: '300px', maxHeight: '200px', overflow: 'auto'}}>{data.map(item => { return map[item] }).join('、')}</div>} placement={'top'}>
						<Icon type={'detail'} className={cn(s.primaryColor, s.cp, s.ml5, s.vam)} />
					</Tooltip>
				</>
			} else {
				res = data.slice(0, 1).map(item => { return map[item] }).join('、')
			}
		}
		return res
	}
	const [isClose, setIsClose] = useState(true)
	const timeClose = open => {
		setIsClose(!open)
	}
	const historyPageData = useMemo(() => {
		const res = historyData.reduce((total, item) => {
			let i = cloneDeep(item)
			if (filter.securityStatus && item.securityStatus !== filter.securityStatus) {
				i = null
			}
			if (i) total.push(i)
			return total
		}, [])
		const resultList = []
		const limit = filter.limit || 10
		if (res?.length > 0) {
			Array(Math.ceil(res.length / limit)).fill('').map((i, k) => {
				resultList.push(res.slice(k*limit, k*limit+limit))
			})
		}
		setTotal(res.length || 0)
		return resultList
	}, [historyData, filter])
	useEffect(() => {
		if (target) {
			getData()
		}
	}, [target])
	useEffect(() => {
		if (isClose && target) {
			getData()
		}
	}, [dateRange, isClose])
	return (
		<div className={cn(className, s.tableContainer, s.pr)}>
			<Loading show={loading} />
			{type === 'history' &&
			<div className={cn(s.df, s.aic, s.jcfe, s.pr10, s.mb20)}>
				<Select
					placeholder="监测结果"
					className={s.item}
					value={[filter.securityStatus]}
					allowClear={true}
					getPopupContainer={triggerNode => triggerNode}
					clearable
					option={[
						{ label: '正常', value: 'safe' },
						{ label: '异常', value: 'warning' },
					]}
					onChange={({ selectedItem }) => handleChangeSearch({ securityStatus: selectedItem[0] ? selectedItem[0].value : ''  })}
				/>
				<Datetime value={dateRange}
					disabledDate={disableDate}
					allowClear={false}
					onOpenChange={timeClose}
					style={{marginLeft: '10px'}}
					onChange={(val, str) => {
						const dateR = cloneDeep(val)
						if (dateR.length === 2) {
							const st = cloneDeep(val[0])
							const maxEndDay = st.add(7, 'd').endOf('day')
							if (dateR[1].endOf('day').unix() > maxEndDay.unix()) {
								dateR[1] = maxEndDay
							}
						}
						setDateRange(dateR)
					}}
					ranges={{}}
					showTime={false} />
			</div>}
			<Table
				columns={columns}
				key={taskType}
				className={cn(s.bborderTable)}
				scroll={type === 'last' ? {
					y: 235
				} : {}}
				expandable={type === 'history' ? {
					columnWidth: 50,
					expandedRowRender: record => {
						const allNode = aviliableNode?.v4_area?.concat(aviliableNode?.v6_area).reduce((t, i) => {
							const item = JSON.parse(JSON.stringify(i));
							delete item.enable;
							t[Object.keys(item)[0]] = item[Object.keys(item)[0]];
							return t
						}, {})
						const settingsIPv4 = record?.taskSettings?.collect?.area?.map(i => { return { node: i, networkDisplayName: 'IPv4' } }) || []
						const settingsIPv6 = record?.taskSettings?.collect?.area_ipv6?.map(i => { return { node: i, networkDisplayName: 'IPv6' } }) || []
						const res = Object.values(record?.result?.addition?.detail?.concat(settingsIPv4)?.concat(settingsIPv6)?.reduce((total, item) => {
							if (!total[`${item.node}_${item.networkDisplayName}`]) {
								if (!item.area) {
									item.area = allNode[item.node]
									item.securityStatus = 'error'
								}
								total[`${item.node}_${item.networkDisplayName}`] = item
							}
							return total
						}, {}) || {})
						return <div>
							<p className={cn(s.p0_10, s.primaryColor)}><span className={s.cp} onClick={() => {
								const settings = cloneDeep(record.taskSettings)
								settings.startTime = record.startTime
								settings.endTime = record.endTime
								settings.taskSessionId = record.taskSessionId
								settings.taskType = record.taskType
								setTaskSettings(settings)
								setVisible(true)
							}}>查看任务信息</span></p>
							<div className={s.maxH190}>
								<div>
									{res?.map(i => {
										return <p className={cn(s.desItem, {[s.pingItem]: record?.taskType === 'ping'})}>
											<span title={i.area}>监测点：{i.area}</span>
											<span title={i.networkDisplayName}>监测类型：{i.networkDisplayName}</span>
											<span title={i.ip || '- -'}>响应服务器IP：{i.ip || '- -'}</span>
											{record?.taskType === 'http' && <span title={i.statusCode}>响应状态码：{i.securityStatus === 'error' ? '- -' : i.statusCode}</span>}
											<span>总响应时间：{i.securityStatus === 'error' ? '- -' : `${i.totalTime}ms`}</span>
											<span>状态：{i.securityStatus === 'warning' ? '异常' : i.securityStatus === 'error' ? '节点出错' : '正常'}</span>
											<span>
												{i.securityStatus === 'error' ? '- -' : <TaskResult
													securityStatus={i.securityStatus}
													result={{...i, endTime: record?.endTime}}
													type="text"
													taskType={record?.taskType}
													withoutIcon={true}
												/>}
											</span>
										</p>
									})}
								</div>
							</div>
						</div>
					}
				} : null}
				data={type === 'history' ? historyPageData[filter.page - 1] : data}
				empty={<Empty className={s.bd0} />}
				pro  />
				<div className={cn(s.df, s.mt20, s.jcfe)}>
					{type === 'history' && total > 10 && (
						<Pagination
							total={total}
							current={filter.page || 1}
							pageSize={filter.limit || 10}
							pageSizeOptions={[10, 20, 50]}
							showSizeChanger
							showQuickJumper
							showTotal={total => `共${total}条`}
							onChange={(page, limit) => {
								handleChangeSearch({ page, limit });
							}}
						/>
					)}
				</div>
			<Dialog title={<div className={cn(s.df, s.aic)}>任务信息<Tooltip overlay='以下配置为该资产当次任务检测时设置的参数。' placement='top'><Icon className={cn(s.cp, s.ml5, s.primaryColor)} type='question' /></Tooltip></div>}
				className={s.w520}
				visible={visible}
				confirmText="关闭"
				onhide={() => setVisible(false)}
				cancelText="">
				<div className={cn(s.p20, s.noStyle)}>
					<p className={s.circle}>{taskSettings?.taskType === 'http' ? 'HTTP' : 'Ping'}监测参数</p>
					<Form
						name="basic"
						labelCol={{ span: 6 }}
						wrapperCol={{ span: 18 }}>
						<Form.Item label="监测节点">
							<div className={s.pt5}>
								<p>IPv4：{taskContent(taskSettings?.collect.area, aviliableNode?.v4_area?.reduce((t, i) => {
									const item = cloneDeep(i)
									if (item.enable) {
										delete item.enable
										t[Object.keys(item)[0]] = item[Object.keys(item)[0]]
									}
									return t
								}, {}))}</p>
								<p>IPv6：{taskContent(taskSettings?.collect.area_ipv6, aviliableNode?.v6_area?.reduce((t, i) => {
									const item = cloneDeep(i)
									if (item.enable) {
										delete item.enable
										t[Object.keys(item)[0]] = item[Object.keys(item)[0]]
									}
									return t
								}, {}))}</p>
							</div>
						</Form.Item>
						<Form.Item label="监测频率">
							{timeChange(taskSettings?.interval)}
						</Form.Item>
						{taskSettings?.taskType === 'http' && <><Form.Item label="HTTP请求方法">
							{taskSettings?.collect?.method?.toUpperCase()}
						</Form.Item>
						<Form.Item label="HTTP请求信息">
							{Object.keys(taskSettings?.collect?.header || {}).length > 0 ? Object.keys(taskSettings?.collect?.header).map(key => {
								return `${key}：${taskSettings?.collect?.header[key]}`
							}) : '- -'}
						</Form.Item>
						{['post', 'put'].includes(taskSettings?.collect?.method) && <Form.Item label="提交内容">
							{taskSettings?.collect?.payload || '- -'}
						</Form.Item>}
						<Form.Item label="重定向次数">
							允许页面最多跳转{taskSettings?.collect?.redirect}次
						</Form.Item></>}
					</Form>
					<p className={cn(s.circle, s.mt20)}>监测时间详情</p>
					<Form
						name="basic"
						labelCol={{ span: 6 }}
						wrapperCol={{ span: 18 }}>
						<Form.Item label="监测开始时间">
							{moment(taskSettings?.startTime).format('YYYY-MM-DD HH:mm:ss')}
						</Form.Item>
						<Form.Item label="监测结束时间">
							{moment(taskSettings?.endTime).format('YYYY-MM-DD HH:mm:ss')}
						</Form.Item>
						<Form.Item label="监测耗时">
							{timeChange(new Date(taskSettings?.endTime).getTime() - new Date(taskSettings?.startTime).getTime())}
						</Form.Item>
						<Form.Item label="监测任务ID">
							{taskSettings?.taskSessionId}
						</Form.Item>
					</Form>
				</div>
			</Dialog>
		</div>
	);
}

InfoTable.propTypes = {
	className: PropTypes.string,
	data: PropTypes.arrayOf(
		PropTypes.shape({
			node: PropTypes.string,
			statusCode: PropTypes.number,
			respTime: PropTypes.number,
			securityStatus: PropTypes.string,
		})
	),
};
InfoTable.defaultProps = {
	className: '',
};

export default InfoTable;
